#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io_utils.h>
typedef long int my_int;

void SwapInt(int *a, int *b) {
  int temp = *a;
  *a = *b;
  *b = temp;
}

void SwapDouble(double *a, double *b) {
  double temp = *a;
  *a = *b;
  *b = temp;
}

void unSupport() {
  puts("is not support error");
}

//error
//void swap2(void *a, void *b){
//  void *temp = a;
//  *a = *b;
//  *b = temp;
//}

void Swap(void *first, void *second, size_t size) {
  void *temp = malloc(size);
  if (temp) {
    memcpy(temp, first, size);
    memcpy(first, second, size);
    memcpy(second, temp, size);

    free(temp);
  } else {
    // ...
    puts("malloc error!");
  }
}

// msvc C++ decltype(a)
#define SWAP(a, b, type) do { type temp = a; a = b; b = temp; }while (0)
#define SWAP_EXT(a, b) do { typeof(a) temp = a; a = b; b = temp; }while (0)
#define SWAP2(a, b) _Generic((a), \
  int: SwapInt(&a,&b),\
  double:SwapDouble(&a,&b),\
  default:unSupport()\
)
int main() {
  int a = 0;
  int b = 1;

  double x = 3.0;
  double y = 4.0;

  // SwapInt
  SwapInt(&a, &b);
  Swap(&x, &y, sizeof(double));

//  if (a) SWAP(a, b, int);
//  else {
//    puts("no swap.");
//  }
  //SWAP_EXT(x, y); // gcc OK; msvc ERROR

  //typeof(a) number = 0; // gcc OK; msvc ERROR
  // int number = 0;

  PRINT_INT(a);
  PRINT_INT(b);
  PRINT_DOUBLE(x);
  PRINT_DOUBLE(y);
  SWAP2(a, b);
  PRINT_INT(a);
  PRINT_INT(b);
  SWAP2(x, y);
  PRINT_DOUBLE(x);
  PRINT_DOUBLE(y);
  return 0;
}
